#include <stdio.h>
#include <pthread.h>
#include "cpu.h"
#include "random.h"

schedule *cancel_cpu_workload(void *);
void *workload_cpu(void *);
schedule *create_cpu_workload(void *);

typedef struct cpu_model cpu_model;

struct cpu_model {
  void *nothing_for_now;
};

resource_model *setup_cpu(cJSON *json) {
  cJSON *distribution, *job_length;
  distribution = cJSON_GetObjectItem(json, "distribution");
  job_length = cJSON_GetObjectItem(json, "job_length");
  if(distribution == NULL)
    {
      exit(1);
    }
  if(job_length == NULL)
    {
      exit(1);
    }
  setup_rng("cpu_rng", distribution);
  setup_rng("cpu_job_length", distribution);
  resource_model *model = malloc(sizeof(resource_model));
  if(model == NULL) {
    exit(1);
  }
  model->birth = create_cpu_workload;
  model->state = NULL;
  return model;
}

/**
 *
 */
schedule *create_cpu_workload(void *args) 
{  
  double next_arrival_ms = get_random_number("cpu_rng");
  double job_length = get_random_number("cpu_job_length");
  event *next_birth = malloc(sizeof(event));
  if(next_birth == NULL) {
	exit(1);
}
  next_birth->timestamp = ms_from_now(next_arrival_ms);
  next_birth->job = create_cpu_workload;
  next_birth->args = args;
  next_birth->next = NULL;
  pthread_t *thread = malloc(sizeof(pthread_t));
  if(thread == NULL) {
    exit(1);
  }
  pthread_create(thread, NULL, workload_cpu, args);
  event *next_cancel = malloc(sizeof(event));
  if(next_cancel == NULL) {
    exit(1);
  }
  next_cancel->timestamp = ms_from_now(job_length);
  next_cancel->job = cancel_cpu_workload;
  next_cancel->args = (void *)thread;
  next_cancel->next = NULL;
  return make_schedule(2, next_birth, next_cancel);

}

/**
 * The actual CPU workload
 */
void *workload_cpu(void *args) {
  unsigned int x = 0;
  while(1) {  
    if(++x%500==0) {
      pthread_testcancel();
    }  
  }
}

/**
 * Cancels a running workload
 */
schedule *cancel_cpu_workload(void *args) {
  pthread_t *t = (pthread_t *)args;
  pthread_cancel(*t);
  return NULL;
}
